package org.noote.libs.radar;

import org.noote.libs.sogle.Mesh;
import org.noote.libs.sogle.Vector3D;

public class Mesh_Radar extends Mesh {

	int _mapX = 0, _mapY = 0; 
	float [][] _depthMap = null;
	float _cellSizeX = 0, _cellSizeY = 0, _cellSizeZ = 0; 
	float _depthMin=0, _depthMax=0;
	
	public void create(int x, int y, float cellSizeX, float cellSizeY, float cellSizeZ)
	{
		_depthMap=new float[x][y];
		_mapX = x;
		_mapY = y;
		_cellSizeX = cellSizeX;
		_cellSizeY = cellSizeY;
		_cellSizeZ = cellSizeZ;
	}
	
	public Vector3D get(int x, int y)
	{
		if(x>-1 && x<_mapX && y>-1 && y<_mapY)
		{
			float midX = (_cellSizeX*_mapX)/2.0f;
			float midY = (_cellSizeY*_mapY)/2.0f;
			return new Vector3D(x*_cellSizeX-midX, y*_cellSizeY-midY, _depthMap[x][y]*_cellSizeZ);
		}
		
		return null;
	}
	public float getDepth(int x, int y)
	{
		if(x>-1 && x<_mapX && y>-1 && y<_mapY)
		{
			return _depthMap[x][y];
		}
		
		return 0;
	}
	public float getMinDepth()
	{
		return _depthMin;
	}
	public float getMaxDepth()
	{
		return _depthMax;
	}
	public boolean set(int x, int y, float d)
	{
		if(x>-1 && x<_mapX && y>-1 && y<_mapY)
		{
			if(d<_depthMin)	_depthMin = d;
			if(d>_depthMax)	_depthMax = d;

			_depthMap[x][y] = d;

			return true;
		}
		
		return false;
	}
	public boolean setMap(int size_x, int size_y, float [] map)
	{
		if(_depthMap == null)
			return false;
		
		float fStepX = (float)size_x/(float)_mapX;
		float fStepY = (float)size_y/(float)_mapY;
		
		float goY = 0;
		for(int y=0; y<_mapY; y++, goY+=fStepY)
		{
			float goX = 0;
			for(int x=0; x<_mapX; x++, goX+=fStepX)
			{
				int mx = (int)goX, my=(int)goY;
				
				float d = map[mx+my*size_x];
				
				if(d<_depthMin)	_depthMin = d;
				if(d>_depthMax)	_depthMax = d;
				
				_depthMap[x][y] = d;
			}
		}
		return true;
	}
	public boolean setMap(int size_x, int size_y, float [] map, boolean bFilter)
	{
		if(_depthMap == null)
			return false;
		
		float fStepX = (float)size_x/(float)_mapX;
		float fStepY = (float)size_y/(float)_mapY;
		
		float goY = 0;
		for(int y=0; y<_mapY; y++, goY+=fStepY)
		{
			float goX = 0;
			for(int x=0; x<_mapX; x++, goX+=fStepX)
			{
				int mx = (int)goX, my=(int)goY;
				
				float d = 0;
				if(bFilter && ((mx+1)<size_x && (my+1)<size_y))
				{
					float dx=goX-mx;
					float dy=goY-my;
					
					float x1=map[mx+my*size_x]*(1.0f-dx) + map[mx+1+my*size_x]*dx;
					float x2=map[mx+(my+1)*size_x]*(1.0f-dx) + map[mx+1+(my+1)*size_x]*dx;
					
					d = x1*(1.0f-dy) + x2*dy;
				}
				else
				{
					d = map[mx+my*size_x];
				}
				
				if(d<_depthMin)	_depthMin = d;
				if(d>_depthMax)	_depthMax = d;
				
				_depthMap[x][y] = d;
			}
		}
		return true;
	}

	public boolean build()
	{
		float[] vertices = new float[_mapX * _mapY * 3];
		float[] colors = new float[_mapX * _mapY * 4];
 		short[] indices = new short[(_mapX-1) * (_mapY-1) * 6];

 		int currentVertex = 0;
 		int currentColor = 0;
 		int currentIndex = 0;
 		short w = (short) (_mapX );
 		for (int y = 0; y < _mapY; y++) {
 			for (int x = 0; x < _mapX ; x++) {
 				Vector3D p3d = get(x, y);
 				
 				vertices[currentVertex] = p3d.x;
 				vertices[currentVertex + 1] = p3d.y;
 				vertices[currentVertex + 2] = p3d.z;
 				currentVertex += 3;
 				
 				float d = 1.0f-getDepth(x, y)/getMaxDepth();
 				colors[currentColor] = d;
 				colors[currentColor + 1] = d;
 				colors[currentColor + 2] = d;
 				colors[currentColor + 3] = 1.0f;
 				currentColor += 4;
 				
 				// put face (2 triangles)
 				if (y<(_mapY-1) && x<(_mapX-1))
 				{
 	 				int n = y * (_mapX ) + x;
 	 				
 					// Face one
 					indices[currentIndex + 2] = (short) n;
 					indices[currentIndex + 1] = (short) (n + 1);
 					indices[currentIndex + 0] = (short) (n + w);
 					// Face two
 					indices[currentIndex + 5] = (short) (n + 1);
 					indices[currentIndex + 4] = (short) (n + 1 + w);
 					indices[currentIndex + 3] = (short) (n + 1 + w - 1);

 					currentIndex += 6;
 				}
 			}
 		}

 		setIndices(indices);
 		setVertices(vertices);
 		setVerticeColors(colors);
 		//buildNormales();
		
		return true;
	}
}
